#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：      allure_reports.py
   Remark :         企业级 Allure 操作报告工具类
-------------------------------------------------
"""

from __future__ import annotations

import json
import logging
import allure

from pathlib import Path
from typing import Any, Optional, Union



# 模块公开接口
__all__ = ["AllureHandler", "allure_handler"]

# Configure logging for AllureHandler
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("AllureHandler")


class AllureHandler:
    """
    企业级 Allure 报告工具类

    提供统一接口生成 Allure 报告，包括步骤、数据和文件附件。
    """

    # 默认附件类型映射表，可扩展
    ATTACHMENT_TYPE_MAP = {
        "txt": "TEXT",
        "uri": "URI_LIST",
        "json": "JSON",
        "xml": "XML",
        "html": "HTML",
        "png": "PNG",
        "jpg": "JPG",
        "jpeg": "JPG",
    }

    def __init__(self):
        """
        初始化 AllureHandler 实例
        """
        logger.info("AllureHandler instance created")

    @staticmethod
    def add_step(step: str, var: Optional[Union[str, dict]] = None,
                 attachment_name: Optional[str] = "Step Data") -> None:
        """
        添加 Allure 步骤并附加可选数据。

        :param step: 操作步骤描述
        :param var: 步骤变量数据，可以是字符串或字典
        :param attachment_name: 附件名称，默认为 "Step Data"
        """
        logger.info(f"Adding allure step: {step}")
        try:
            with allure.step(step):
                if var:
                    AllureHandler.attach_data(
                        body=var,
                        name=attachment_name,
                        attachment_type="JSON" if isinstance(var, dict) else "TEXT",
                    )
        except Exception as e:
            logger.error(f"Failed to add allure step: {step} | Error: {e}")
            raise

    @staticmethod
    def attach_data(body: Any, name: str = "Attachment", attachment_type: str = "JSON",
                    extension: Optional[str] = None) -> None:
        """
        添加自定义数据到 Allure 报告。

        :param body: 数据内容，可以是字符串或字典
        :param name: 附件名称
        :param attachment_type: 附件类型，默认为 JSON
        :param extension: 附件扩展名（可选）
        """
        try:
            logger.debug(f"Attaching data: {name} | Type: {attachment_type}")
            if isinstance(body, dict):
                body = json.dumps(body, ensure_ascii=False, indent=4).encode("utf-8")
            elif isinstance(body, str):
                body = body.encode("utf-8")
            allure.attach(
                body=body,
                name=name,
                attachment_type=attachment_type,
                extension=extension,
            )
        except Exception as e:
            logger.error(f"Failed to attach data: {name} | Error: {e}")
            raise

    @staticmethod
    def attach_file(filepath: str, name: Optional[str] = None, extension: Optional[str] = None) -> None:
        """
        添加文件到 Allure 报告。

        :param filepath: 文件路径
        :param name: 附件名称，默认为文件名
        :param extension: 附件扩展名（可选）
        """
        try:
            file_path = Path(filepath)
            if not file_path.exists():
                raise FileNotFoundError(f"File not found: {filepath}")

            filetype = file_path.suffix[1:].lower()
            attachment_type = AllureHandler.ATTACHMENT_TYPE_MAP.get(filetype, "TEXT")

            logger.info(f"Attaching file: {filepath} | Type: {attachment_type}")
            allure.attach.file(
                source=str(file_path),
                name=name or file_path.name,
                attachment_type=attachment_type,
                extension=extension,
            )
        except Exception as e:
            logger.error(f"Failed to attach file: {filepath} | Error: {e}")
            raise

    @staticmethod
    def attach_image(filepath: str, name: Optional[str] = None) -> None:
        """
        添加图片到 Allure 报告。

        :param filepath: 图片文件路径
        :param name: 图片显示名称，默认为文件名
        """
        try:
            logger.info(f"Attaching image: {filepath}")
            allure.attach.file(
                source=filepath,
                name=name or "Screenshot",
                attachment_type='png',
            )
        except Exception as e:
            logger.error(f"Failed to attach image: {filepath} | Error: {e}")
            raise

    @staticmethod
    def attach_text(text: str, name: Optional[str] = "Text Attachment", extension: Optional[str] = None) -> None:
        """
        添加纯文本到 Allure 报告。

        :param text: 文本内容
        :param name: 附件名称
        :param extension: 附件扩展名（可选）
        """
        try:
            logger.debug(f"Attaching text: {name}")
            allure.attach(
                body=text,
                name=name,
                attachment_type="text/plain",
                extension=extension,
            )
        except Exception as e:
            logger.error(f"Failed to attach text: {name} | Error: {e}")
            raise


# 全局实例化，便于外部调用
allure_handler = AllureHandler()

# 示例用法
if __name__ == "__main__":
    # 添加步骤和变量
    allure_handler.add_step(
        step="验证用户登录",
        var={"username": "test_user", "status": "success"},
        attachment_name="登录验证数据",
    )

    # 添加 JSON 数据
    allure_handler.attach_data(
        body={"key": "value"},
        name="示例 JSON 数据",
        attachment_type="JSON",
    )

    # 添加文件
    # allure_handler.attach_file(
    #     filepath="example.json",
    #     name="JSON 文件附件",
    # )

    # 添加图片
    allure_handler.attach_image(
        filepath="screenshot.png",
        name="截图附件",
    )

    # 添加文本
    allure_handler.attach_text(
        text="这是一段简单的文本内容",
        name="文本附件",
    )
